# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# Name:        модуль1
# Purpose:
#
# Author:      daimoon
#
# Created:     17.11.2013
# Copyright:   (c) daimoon 2013
# Licence:     <your licence>
#-------------------------------------------------------------------------------
import sys
sys.path.append('./modules')
import numpy as np
from random import *
import estimate as est
import pylab as plt
import const
import graf_prantl as graph
import lptau
from math import *
import matplotlib.ticker
pi = 3.14
def t(txt):
    try:
        out = txt.encode('cp1251').decode('utf8')
    except UnicodeDecodeError:
        out = txt
    return out
plt.ion()
class gen(object):
    def __init__(self):
        # Параметры алгоритма
        self.mutation = 0.25
        self.max_probability = 10000
        self.roundfn = 5

        # Позиции данных в массиве
        self.fitness_position = 1
        self.probability_position = 2
        self.variables_start_position = 3

        # Начальная инициализация
        self.test = 0
        self.filter = 1
        self.type_new = 'lptau'
        self.purge()

    def purge(self):
        self.max_fn = const.bed_fitness
        self.n_el1 = 30
        self.n_el2 = 100
        self.generation = 1
        self.n_ekz = 0
        self.minmax = np.zeros(0)
        self.array = np.zeros(0)
        self.best_var = 0
        self.bed_fitness = const.bed_fitness
        self.percent_bed = 0
        self.stop = 0
        self.bad_population = 0
        self.min_fitness = self.bed_fitness
        self.old_fitness = self.bed_fitness
        self.collect_out = []
        self.probability_min = 0.05
        self.ignore_confines = 0
        self.inf('Очистка произведена')

    def inf(self, txt, end = '\n'):
        if end != '\n':
            if self.test: print(t(txt), end = '')
        else:
            if self.test: print(t(txt))

    def set_confines(self, confines):
        self.n_variables = 0
        self.confines = []
        self.const = []
        for i in confines:
            if i[0] != i[1]:
                self.confines.append([i[0],i[1]])
                self.n_variables += 1
            else:
                self.const.append(i[0])
        self.dtype = []
        self.list_variables = []
        for i in range(0, self.variables_start_position + self.n_variables):
            self.dtype.append(('var' + str(i), float))
            if i >= self.variables_start_position:
               self.list_variables.append('var' + str(i))
        self.inf('Заданы ограничения ' + str(self.n_variables))

    def set_gen_stop(self, n_stop, max_gen):
        self.n_stop = n_stop
        self.max_gen = max_gen

    def soil_characteristics(self, b, phi, sc, gam, q):
        self.b = b
        self.phi = phi * (pi / 180)
        self.sc = sc
        self.gam = gam
        self.q = q
        self.Nmin = max(self.Nprantl(b, self.phi, sc, gam, q), self.Nsnip(b, phi, sc, gam, q))
        self.inf('Заданы характеристики')

    def Nprantl(self, b, phi, sc, gam, q):
        ctg = lambda x: 1 / tan(x)
        N = ((q + sc * ctg(phi)) * (1 + sin(phi))/(1 - sin(phi))) * (e ** (pi * tan(phi))) - sc * ctg(phi)
        print(t('Несущая способность по Прандтлю - ' + str(round(N * b, self.roundfn))))
        return round(N * b, self.roundfn)

    def interp_N(self, N, i, phi):
        return const.Nkoeff[i][N] + ((phi - const.Nkoeff[i]['phi']) * (const.Nkoeff[i+1][N] - const.Nkoeff[i][N])) / (const.Nkoeff[i+1]['phi'] - const.Nkoeff[i]['phi'])

    def Nsnip(self, b, phi, sc, gam, q):
        eta = 1
        ksi_g = 1 - 0.25 / eta
        ksi_q = 1 + 1.5 / eta
        ksi_c = 1 + 0.3 / eta
        if phi < const.Nkoeff[const.Nkoeff.size-1]['phi']:
            for i in range(const.Nkoeff.size-1):
                if phi == const.Nkoeff[i]['phi']:
                    N_g = const.Nkoeff[i]['N_g']
                    N_q = const.Nkoeff[i]['N_q']
                    N_c = const.Nkoeff[i]['N_c']
                elif phi > const.Nkoeff[i]['phi'] and phi < const.Nkoeff[i+1]['phi']:
                    N_g = self.interp_N('N_g', i, phi)
                    N_q = self.interp_N('N_q', i, phi)
                    N_c = self.interp_N('N_c', i, phi)
        else:
            N_g = const.Nkoeff[const.Nkoeff.size-1]['N_g']
            N_q = const.Nkoeff[const.Nkoeff.size-1]['N_q']
            N_c = const.Nkoeff[const.Nkoeff.size-1]['N_c']
        N_g, N_q, N_c = N_g[0], N_q[0], N_c[0]
        N_1 = N_g * ksi_g * b * gam
        N_2 = N_q * ksi_q * q
        N_3 = N_c * ksi_c * sc
        N = (N_1 + N_2 + N_3) * b
        print(t('Несущая способность по СНиП - ' + str(round(N, self.roundfn))))
        return round(N, self.roundfn)

    def p_size(self, population_size, n_elit, n_selection):
        if population_size: self.population_size = int(abs(population_size))
        n = lambda population_size, n: int(population_size * n) + (int(population_size * n) == 0)
        if n_elit:
            self.n_elit =  n(self.population_size, n_elit)
        else:
            self.n_elit =  0
        if n_selection:
            self.n_selection = n(self.population_size, n_selection)
        else:
            self.n_selection = 0
        self.n_new = int(abs(self.population_size - self.n_elit - self.n_selection))
        self.re_distribution(self.n_new)

    def add_array(self, population):
        '''
        Запись в архив
        array:
        -------------------------------------------------------------
        | Номер_пп | Фитнесс | Вероятность| Перем_1 | ... | Перем_N |
        -------------------------------------------------------------
        minmax:
        -----------------------------------------------------------------------------
        | Поколение | Мин. фитнесс | Перем_1 | ... | Перем_N | Мутация | % штрафных |
        -----------------------------------------------------------------------------
        '''
        if self.generation == 1: self.array = population
        if population[0][0][0] != 0:
            n = 0
        else:
            n = 1
        var = [self.best_variables(population, n)[i] for i in range(self.n_variables)]
        if self.stop < 2 or self.stop > self.n_stop - 2:
            self.n_data = self.n_variables + 5
            data = np.zeros(self.n_data)
            data[0] = self.generation
            data[1] = population[n][0][self.fitness_position]
            data[2:self.n_variables + 2] = var
            data[self.n_variables + 2] = self.mutation
            data[self.n_variables + 3] = self.percent_bed
            data[self.n_variables + 4] = self.koeff_distribution
            self.minmax = np.append(self.minmax, data, axis = 0)
            self.array = np.append(self.array, population, axis = 0)
        if self.min_fitness > population[n][0][self.fitness_position]:
            self.min_fitness = population[n][0][self.fitness_position]
            self.best_var = var
        if self.generation < 2: self.best_var = var

    def minmax_out(self):
        '''
        Разбивка массивов перед выводом
        '''
        if self.generation > 1:
            minmax = self.minmax.reshape(self.minmax.size/self.n_data, self.n_data)
        else:
            minmax = self.minmax.reshape(1, self.minmax.size)
        return minmax

    def array_filter(self, minmax):
        '''
        В общем массиве оставляет все варианты с приспособлением больше 0.01
        В массиве поколений оставляет все варианты, за исключением последних self.stop
        Массив поля скоростей выводится соответственно обшему массиву.
        '''
        array = np.sort(self.array, order='var0', axis = 0)
        if self.filter:
            array_out = np.copy(array)
            probability = array['var' + str(self.probability_position)]
            k = 0
            j = 0
            for i in probability:
                if round(i[0], self.roundfn) > self.probability_min*1.5 and j<probability.size:
                    array_out[j] = array_out[k]
                    j+=1
                k+=1
            array_out = array_out[0:j]
        else:
            array_out = array
        return array_out, minmax

    def shape(self, population):
        try:
            rows = population.shape[0]
            cols = len(population[0][0])
        except:
            rows = 0
            cols = 0
        return rows, cols

    def best_variables(self, population, n = 0):
        rows, cols = self.shape(population)
        if rows and cols:
            if population[n][0][self.fitness_position] == 0: n+=1
            array_variables = population[n][self.list_variables][0]
        else:
            array_variables = np.zeros(0)
            for i in self.confines:
                n = i[1] -  abs(i[1] - i[0]) * 0.5
                array_variables = np.append(array_variables, n)
        return array_variables

    def add_field(self, population, n_el):
        emepty = np.zeros((n_el, self.variables_start_position))
        population = np.hstack((emepty, population))
        population.dtype = self.dtype
        return population

    def re_distribution(self, n_new):
        if self.generation < 2 or self.distribution_array.shape[0] < n_new:
            n_new = int(abs(n_new))
            if self.type_new == 'lptau' and n_new > 2000:
                distribution_array_1 = lptau.m_lptau(2000, self.n_variables)
                distribution_array_2 = np.random.uniform(0, 0.8, (n_new - 2000) * self.n_variables)
                distribution_array_2 =  distribution_array_2.reshape((n_new - 2000, self.n_variables))
                self.distribution_array = np.vstack((distribution_array_1, distribution_array_2))
            elif self.type_new == 'lptau'and n_new <= 2000:
                self.distribution_array = lptau.m_lptau(n_new, self.n_variables)
            elif self.type_new == 'unoform':
                self.distribution_array = np.random.uniform(0, 1, n_new * self.n_variables)
                self.distribution_array =  self.distribution_array.reshape((n_new, self.n_variables))
            elif self.type_new == 'normal':
                self.distribution_array = np.random.normal(0.1, 0.05, n_new * self.n_variables)
                self.distribution_array =  self.distribution_array.reshape((n_new, self.n_variables))
            self.inf('-!массив увеличен до ' + str(self.distribution_array.shape[0]) + ' недобор = ' + str(self.distribution_array.shape[0] - n_new), end='')

    def distribution_gen(self, array_variables, n_var):
        '''
        ЛПТау
        Генерация n_var пробных вариантов около array_variables с разбросом self.koeff_distribution
        '''
        array_out = np.zeros(0, dtype = float)
        self.re_distribution(n_var)
        array_variables = [i - 0.5 * self.koeff_distribution for i in array_variables]
        array_out = np.append(array_out, [array_variables + self.koeff_distribution * self.distribution_array[i] for i in range(0, n_var)])
        array_out = np.around(array_out.reshape(n_var, self.n_variables),decimals=self.roundfn)
        array_out = self.add_field(array_out, n_var)
        return array_out

    def new_population(self, array_variables, population_size):
        flatten_confines = [val for subl in self.confines for val in subl]
        if self.generation < 2:
            koeff_distribution = max(flatten_confines) - min(flatten_confines)
#            population_size = min(population_size ** 2, 10000)
            array_variables = self.best_variables(0)
        else:
            koeff_distribution = abs(self.mutation) * 5
            if abs(self.mutation) > 0.5:
                koeff_distribution = abs(self.mutation) * 5
            else:
                if self.stop * 0.1 > max(flatten_confines) - min(flatten_confines):
                    koeff_distribution = self.stop * 0.01
                    population_size = population_size * 2
                else:
                    koeff_distribution = self.stop * 0.05

        self.koeff_distribution  = round(koeff_distribution , self.roundfn)
        distribution = self.distribution_gen(array_variables, population_size)
        return distribution

    def fitness(self, population):
        rows, cols = self.shape(population)
        count_bed = 0
        for i in range(0, rows, 1):
            self.n_ekz += 1
            variables = []
            decision = 1
            k = 0
            while k < 5 and (decision or self.ignore_confines):
                #Проверяем - находится ли переменная в заданных пределах
                try:
                    x =  population[i][0][self.variables_start_position + k]
                    decision *= (x > self.confines[k][0] and x < self.confines[k][1])
                except IndexError:
                    x =  self.const[k - self.n_variables]
                    decision *= 1
                finally:
                    variables.append(x)
                    k += 1
            if decision or self.ignore_confines:
                x, y, z, k1, k2 = variables
                fn, X, Y, u, v, u1, v1 = est.estimate(x, y, z, self.b, self.phi, self.sc, self.gam, self.q, self.n_el1, self.n_el2, k1, k2)
                self.out(x, y, z, k1, k2, fn, X, Y, u, v, u1, v1)
                fn = fn - self.Nmin
            else:
                fn = self.bed_fitness
            if round(abs(fn), self.roundfn) == 0:
                self.stop = self.n_stop - 2
                fn = 1 / 10 ** (self.roundfn - 1)
            if fn < 0: fn = self.bed_fitness * abs(fn)
            if fn == self.bed_fitness: count_bed += 1
            population[i][0][self.fitness_position] = round(abs(fn), self.roundfn)
            population[i][0][0] = self.n_ekz
            if fn != self.bed_fitness :
                max_fn_t = min(population[i][0][self.fitness_position], self.max_fn)
                if abs(max_fn_t - self.max_fn) > 1:
                    self.collect_out.append([X, Y, u, v, u1, v1])
                    self.max_fn = max_fn_t
        self.percent_bed = (count_bed / rows) * 100
        population = np.sort(population, order='var' + str(self.fitness_position), axis = 0)
        return population

    def koeff_s(self, population):
        s = 0
        rows, cols = self.shape(population)
        for i in range(0,population.shape[0]):
            s = s + 1 / population[i][0][self.fitness_position]
        return round(s,self.roundfn)

    def probability(self, population):
        '''
        Вероятность
        '''
        rows, cols = self.shape(population)
        s = self.koeff_s(population)
        for i in range(0, rows):
            population[i][0][self.probability_position] = round(self.max_probability / (s + population[i][0][self.fitness_position]), 5)
            if population[i][0][self.probability_position] < self.probability_min:
                population[i][0][self.fitness_position] = self.bed_fitness
                population[i][0][self.probability_position] = 0
        population = np.sort(population, order='var' + str(self.probability_position), axis = 0)[::-1]
        return population

    def selection(self, population, n_var, illust_k = 0, sdvig = 4):
        '''
        Адаптивное скрещивание
        '''
        rows, cols = self.shape(population)
        cascade_one = np.zeros((n_var, cols))
        copy = np.copy(np.roll(population, sdvig)) #родители получены сдвигом полпуляции на sdvig позиции
        if self.mutation > 2: np.random.shuffle(copy) #при большом значении мутации родители случайны
        k = 0
        for i in range(0, n_var-1):
            for j in range(self.variables_start_position, self.variables_start_position + self.n_variables):
                if illust_k == 0:
                    mutation = int((abs(self.mutation) * 100))
                    mut = 0
                    #Случайный ненулевой коэфф. мутации в заданных пределах
                    while not mut:
                        mut = randint(-mutation, (mutation + 100)) / 100
                    #Приращение к исходному значению, ненулевое
                    prir = mut * (population[i][0][j] - copy[i][0][j])
                    if not round(prir, self.roundfn):
                        while not round(prir, self.roundfn):
                            prir = randint(-mutation, (mutation + 100)) / 200
                    #Вычисление потомства
                    if randint(0, 3) > 1:
                        if randint(0, 2) > 1:
                            cascade_one[k][j] = round(population[i][0][j]  + prir, 4)
                        else:
                            cascade_one[k][j] = round(population[0][0][j]  + prir, 4)
                    else:
                        if randint(0, 2) > 1:
                            cascade_one[k][j] = round(copy[i][0][j]  + prir, 4)
                        else:
                            cascade_one[k][j] = round(copy[i][0][j], 4)
                #Для иллюстрации - полностью ручное вычисление без рандома.
                else:
                    cascade_one[k][j] = round(population[i][0][j]  + illust_k * (population[i][0][j] - copy[i][0][j]), 4)
            k += 1
        cascade_one.dtype = self.dtype
        return cascade_one

    def elit(self, population, n_elit):
        '''
        Отбор уникальных элитных особей
        '''
        population = np.roll(population[0:n_elit+1], 1)
        n = np.append(np.zeros((1, self.variables_start_position)), self.best_var)
        n.dtype = self.dtype
        population[0] = n
        return population[0:n_elit]

    def warp(self, population, arr_best_var):
        '''
        Формирование популяции
        '''
        elit = self.elit(population, self.n_elit)
        selection = self.selection(population, self.n_selection)
        new = self.new_population(arr_best_var, self.n_new)
        population = np.vstack((elit, selection, new))
        return population

    def iteration_1(self):
        arr_best_var = self.best_variables(0)
        population = self.new_population(arr_best_var, self.population_size)
        population = self.fitness(population)
        population = self.probability(population)
        self.add_array(population)
        self.old_fitness = self.min_fitness
        minmax = self.minmax_out()
        rise = 0
        return population, self.array, minmax, rise, self.collect_out

    def iteration_test(self):
        k_mut = 1
        #Первое поколение
        self.generation = 1
        arr_best_var = self.best_variables(0)
        population = self.new_population(arr_best_var, self.population_size)
        population = self.fitness(population)
        population = self.probability(population)
        self.add_array(population)
        minmax = self.minmax_out()
        rise = 0
        self.generation = 2
        #Сборка новой популяции
        arr_best_var = self.best_variables(population)
        elit = self.elit(population, self.n_elit)
        selection = self.selection(population, self.n_selection, k_mut)
        new = self.new_population(arr_best_var, self.n_new)
        population = np.vstack((elit, selection, new))

        population = self.fitness(population)
        population = self.probability(population)
        self.add_array(population)
        array, minmax = self.array_filter(self.minmax_out())
        return population, array, minmax, rise, out

    def iteration_n(self, population):
        arr_best_var = self.best_variables(population)
        population = self.warp(population, arr_best_var)
        population = self.fitness(population)
        population = self.probability(population)
        self.add_array(population)
        self.generation += 1
        rise = 0
        self.stop += 1
        if self.generation > self.max_gen * 0.5:
            self.stop += 1
        if self.stop > self.max_gen * 0.3:
            self.stop += 1
        self.bad_population += self.population_size
        if self.old_fitness != self.min_fitness:
            rise = self.old_fitness - self.min_fitness
            self.old_fitness = self.min_fitness
            self.stop = 0
            self.bad_population = 0
            self.inf('_')
        if self.stop > self.n_stop - 1 or self.generation > self.max_gen - 1:
            array, minmax = self.array_filter(self.minmax_out())
            out = self.collect_out
        else:
            array, minmax = self.array_filter(self.minmax_out())
            out = 0
        return population, array, minmax, rise, out

    def lptau_find(self):
        '''
        Поиск решения
        '''
        self.generation = 1
        self.inf(str(self.generation) + ' - поколение: параметры', end = ' ')
        arr_best_var = self.best_variables(0)
        population = self.new_population(arr_best_var, self.population_size)
        population = self.fitness(population)
        population = self.probability(population)
        self.add_array(population)
        array, minmax = self.array_filter(self.minmax_out())
        rise = 0
        return population, array, minmax, rise, self.collect_out

    def out(self, x, y, z, k1, k2, fn, X, Y, u, v, u1, v1):
        pass

def koord(array, position, tip_mass, tip_out, koeff, max_f = 30):
    arr_out = np.zeros(array.shape[0])
    if tip_mass == 'base':
        el = lambda arr, i, j: arr[i][0][j]
    elif tip_mass == 'minmax':
         el = lambda arr, i, j: arr[i][j]
    for i in range(0, array.shape[0]):
        if tip_out == 'simple':
            arr_out[i] = el(array, i, position) * koeff
        elif tip_out == 'log':
            arr_out[i] = (3 / (log10(el(array, i, position)*koeff + koeff) + 1))
        elif tip_out == 'log_w':
            arr_out[i] = log10(el(array, i, position) + 1) * koeff
        elif tip_out == 'log_w_limit':
            f = el(array, i, position)
            if f > max_f:
                f = f/max_f
                arr_out[i] = f * koeff
        elif tip_out == '1/x':
                arr_out[i] =   koeff / (el(array, i, position) + 1)
    return arr_out

def graph_prantl():
    xl, yl = graph.graf_prantl(p.phi, p.b)
    one = [p.b * 0.5 for i in range(xl.size)]
    xl = xl + one
    max_x = max(xl.flatten())
    max_y = -min(yl.flatten())
    plt.plot(xl, yl, linewidth=1, label=t('Решение Прандтля'), color='red', linestyle=':')
    plt.xlim (-max_x * 0.1, max_x * 1.1)
    plt.ylim (-max_y * 1.1, max_y * 0.1)
    plt.legend(loc='best')
    plt.draw()

def graph_version(ar, mn, p):
    fn = koord(ar, p.fitness_position, 'base', '1/x', 1)
    gx = koord(ar, 3, 'base', 'simple', 1)
    gy = koord(ar, 4, 'base', 'simple', 1)
    gmx = koord(mn, 2, 'minmax', 'simple', 1)
    gmy = koord(mn, 3, 'minmax', 'simple', 1)
    norm = plt.Normalize()
    norm.autoscale(fn)
    cmap = plt.cm.hot
    clr = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
    plt.scatter(gx, gy, c = clr.to_rgba(fn), alpha=.5, label=t('Варианты'))
    plt.plot(gmx, gmy, 'g-', linewidth=2, label=t('Лучший результат'))
    plt.xlabel('l')
    plt.ylabel('l1')
    plt.xlim (-0.2*p.confines[0][0], p.confines[0][1])
    plt.ylim (-0.2*p.confines[1][0], p.confines[1][1])
    plt.legend(loc='best')
    plt.draw()

def graf_gen(mn, p, name_param, lab = t('Наименьшая оценка'), cl = 'k'):
    scale = 'linear'
    label_line = '_nolegend_'
    label_axis = ' '
    if name_param == 'fitness':
        n = 1
        label_line = lab
        label_axis = t('Нагрузка, кН')
        scale = 'log'
    elif name_param == 'mutation':
        n = p.n_variables + 2
        label_axis = t('Коэфф. мутации')
    elif name_param == 'percent_bed':
        n = p.n_variables + 3
        label_axis = t('Количество плохих особей')
    elif name_param == 'koeff_distribution':
        n = p.n_variables + 4
        label_axis = t('Коэфф. распространения')
    fmx = koord(mn, n, 'minmax', 'simple', 1)
    if n == 1 : fmx = fmx + p.Nmin
    gm = koord(mn, 0, 'minmax', 'simple', 1)

    figure = plt.figure()
    axes = figure.add_subplot (1, 1, 1)

    plt.title (t('Значения верхней оценки'))

    axes.plot(gm, fmx, c = cl)

    # Установим локатор для главных меток
    axes.xaxis.set_major_locator (matplotlib.ticker.MultipleLocator (base = 5))
    axes.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator (base = 3000))

    axes.grid()

    if label_line != '_nolegend_': plt.legend(loc='best')
    plt.ylabel(label_axis)
    plt.xlabel(t('Поколение'))
    plt.draw()

def graph_velocity(collect_out, p):
    for out in collect_out:
        x_o, y_o = est.chi(out)
        plt.plot(y_o, -x_o, label='_nolegend_', linewidth=0.5, color=str(0.5), linestyle='dashed')
    plt.plot(0, -1, label=t('Промежуточные варианты'), linewidth=2, color=str(0.5), linestyle='dashed')
    out = collect_out[::-1][0]
    x_o, y_o = est.chi(out)
    plt.plot(y_o, -x_o, label='_nolegend_', linewidth=1, color='black')
    plt.plot(out[1], -out[0], linewidth=0.7, color='black', label=t('Наилучший вариант с N=') + str(round(p.min_fitness + p.Nmin)) + t('кН'))
    plt.legend(loc='best')
    plt.draw()

def graph_param(array, p, n):
    gx = koord(array, 2 + n, 'base', 'simple', 1)
    plt.yscale('log')
    fnm = koord(array, p.fitness_position, 'base', 'simple', 1)
    plt.scatter(gx, fnm)
    plt.draw()
#
#
#b = 2
#phi = 34.5
#sc = 1
#gam = 17.5
#q = 17.5
#confines =  [[0,5], [0,5], [0,5], [0, 0], [0, 0]] #l, l1, h, k_l, k_l1
##ПОстроить график зависимости угла от верхних оценок.
##Критерий выбора - близость к решению Прандтля
#
#p_size = 25
#n_elit = 0.1
#n_selection = 0.6
#ogr_stop = 300
#mutation = 1.6
#
#type_new = np.array(['lptau', 'unoform', 'normal'])
#
#p = gen()
#p.test = 0
#p.filter = 0
#p.ignore_confines = 0
#p.soil_characteristics(b, phi, sc, gam, q)
#p.set_confines(confines)
#p.set_gen_stop(ogr_stop, 10000)
#p.p_size(p_size, n_elit, n_selection)
#population, array_first, minmax_first, rise, out_first  = p.iteration_1()
#array, minmax, out = array_first, minmax_first, out_first
#
#
#while p.stop < p.n_stop and p.generation < p.max_gen:
#    p.test = 0
#    p.p_size(p_size, n_elit, n_selection)
#    population, array, minmax, rise, out  = p.iteration_n(population)
#    if round(rise) == 0 or p.percent_bed > 90:
#        n_elit = 0.1
#        n_selection = 0.6
#        p.mutation += 0.1
#    else:
#        n_selection = 0.8
#        n_elit = 0.2
#        p.mutation -= 0.1
#    if round(rise) != 0:
#         p.test = 1
#         p.inf('Поколение -' + str(p.generation) + '  улучшение -' + str(rise) + ' N=' + str(p.min_fitness + p.Nmin))
#    if abs(p.mutation) > 2 or p.percent_bed > 90:
#        p.mutation = 0.25
#    stop = p.stop
#print(t('М. Поколение -' + str(p.generation) + '  улучшение -' + str(rise) + ' Nmin=' + str(round(p.min_fitness + p.Nmin))))
##
#plt.subplot (2, 1, 1)
#plt.title (t('Поле скоростей'))
#graph_velocity(out, p)
##graph_prantl()
#plt.subplot (2, 1, 2)
#plt.title (t('Варианты'))
#graph_version(array, minmax, p)
###
###
#graf_gen(minmax, p, 'fitness')
#
#
#    ill = "mt"
#    g = lambda n, massiv: [st[0][n] for st in massiv]
#    if ill == "rand":
#        n_var = 300
#        for i in [0, 1]:
#            gx = 2
#            gy = 2
#            r = 20
#            plt.subplot (1, 2, i+1)
#            p.type_new = type_new[i]
#            array_variables = [gx, gy, 1]
#            plt.scatter(gx, gy, marker='o', s = 100)
#            p.koeff_distribution = 0.1
#            massiv_1 = p.distribution_gen(array_variables, n_var)
#            gx = g(3, massiv_1)
#            gy = g(4, massiv_1)
#            plt.scatter(gx, gy, marker='v', s = r)
#            plt.legend(loc='best')
#            plt.ylabel(t('Параметр 1'))
#            plt.xlabel(t('Параметр 2'))
#    elif ill == "mut":
#        n_var = 300
#        gx = 2
#        gy = 2
#        r = 20
#        p.type_new = type_new[0]
#        array_variables = [gx, gy, 1]
#        plt.scatter(gx, gy, marker='o', s = 100, label=t('исходная точка'))
#        p.koeff_distribution = 0.1
#        massiv_1 = p.distribution_gen(array_variables, n_var)
#        gx = g(3, massiv_1)
#        gy = g(4, massiv_1)
#        plt.scatter(gx, gy, marker='v', s = r, label=t('Кmut=0.1'))
#        p.koeff_distribution = 0.05
#        massiv_2 = p.distribution_gen(array_variables, n_var)
#        gx = g(3, massiv_2)
#        gy = g(4, massiv_2)
#        plt.scatter(gx, gy, marker='x', s = r, label=t('Кmut=0.05'))
#        plt.legend(loc='best')
#        plt.ylabel(t('Параметр 1'))
#        plt.xlabel(t('Параметр 2'))
#    elif ill == "krazb":
#        p.mutation = 0.1
#        n_var = 20
#        p.type_new = type_new[0]
#        array_variables = [2, 2, 2]
#        massiv = p.new_population(array_variables, n_var)
#        gxb = g(3, massiv)
#        gyb = g(4, massiv)
#        n1 = t('Кразб = 0.01, сдвиг на 2 позиции')
#        n2 = t('Кразб = 0.5, сдвиг на 2 позиции')
#        n3 = t('Кразб = 0.01, сдвиг на 6 позиций')
#        n4 = t('Кразб = 0.01, сдвиг на 2 позиции')
#        var = [[2, 0.01, 'v', 1, n1], [2, 0.5, '+', 1, n2], [10, 0.1, 'v', 2, n3], [2, 0.1, '+', 2, n4]]
#        for i in var:
#            sdvig, krazb, mark, n, l = i
#            plt.subplot (1, 2, n)
#            selection = p.selection(massiv, n_var * 4, krazb, sdvig)
#            gx = g(3, selection)
#            gy = g(4, selection)
#            if krazb == 0.5: plt.scatter(gxb, gyb, marker='.', s = 10,  label = t('исходные точки'))
#            if sdvig == 10: plt.scatter(gxb, gyb, marker='.', s = 10,  label = t('исходные точки'))
#            plt.scatter(gx, gy, marker=mark, s = 30, label = l)
#            plt.legend(loc='best')
#            plt.ylabel(t('Параметр 1'))
#            plt.xlabel(t('Параметр 2'))




